import math
from enum import Enum

from phot_engine.globals import ConversionError
from phot_engine.globals import constants

"""
    这个类用于单位转换,需要提供4个必选参数分别是
        1. conversionType: 转换类型
        2. value:值
        3.old_unit:旧单位
        4.new_unit:新单位
        5,6. param_1,param_2:空闲参数,在一些特定的转换场景中可能会用到
    This class is used to convert value
    The class needs:
        1. conversionType: Enum type,to specify unit type
        2. value:a number
        3. old_unit:before converting string type parameter
        4. new_unit:after converted string type parameter
        5,6.param_1,param_2: spare param
"""

MIN_POWER_VALUE = 1e-100  # 功率最小值 minimum power
MIN_VALUE = 1e-100  # 数的最小值 the minimum value of the number


class UnitConversion(object):
    POWER_UNIT = ["mW", "W", "kW", "nW", "uW", "dBm"]
    FREQUENCY_UNIT = ["Hz", "kHz", "MHz", "GHz", "THz", "a"] # "m", "mm", "um", "nm",
    DISTANCE_UNIT = ["nm", "um", "mm", "cm", "m", "km"]
    ANGELE_TYPE = ["rad", "deg", "mrad", "urad"]
    TIME_TYPE = ["h", "min", "s", "ms", "us", "ns", "ps", "fs"]
    BANDWIDTH_UNIT = []

    class UnitConversionEnumType(Enum):
        typePower = 0  # represents the conversion unit to power [mW,W,kW]
        typeFrequency = 1  # represents the conversion unit to frequency [Hz,kHz,MHz,GHz,THz]
        typeBandwidth = 2  # represents the conversion unit to bandwidth [m,mm,nm,ps,un]
        typeTime = 3  # represents the conversion unit to time [ps,ns,μs,ms,s]
        typeErDensity = 4
        typeBitRate = 5  # [bit/s,kbit/s,Mbit/s,Gbit/s]
        typePSD = 6
        typeAngle = 7  # 角度与弧度转换 Angle and radian conversion
        typeDispersion = 8
        typeVoltageGain = 9
        typeLoss = 10
        typeReflection = 11
        typeDistance = 12  # 距离单位转换[nm,um,mm,cm,m,km]
        typeTemperature = 13  # 温度单位转换 [K,F,C]
        typeDispersionSlope = 14
        typeDepolarizationRate = 15
        typePhaseSlope = 16
        typeTemperatureRate = 17  # [/℃,/℉,/K]
        typeEngineeringScale = 18

    def convert(self, conversion_type, value, old_unit, new_unit, param_1=None, param_2=None):
        if conversion_type is None or value is None or old_unit is None or new_unit is None:
            raise ConversionError("conversionType, value, old_unit, new_unit should not None",
                                  conversion_type, value, old_unit, new_unit)
        else:
            if isinstance(value, int) or isinstance(value, float):
                if conversion_type == self.UnitConversionEnumType.typePower:
                    return self.convert_power_unit(value, old_unit, new_unit)
                elif conversion_type == self.UnitConversionEnumType.typeFrequency:
                    return self.convert_frequency_unit(value=value,
                                                       old_unit=old_unit,
                                                       new_unit=new_unit)
                elif conversion_type == self.UnitConversionEnumType.typeBandwidth:
                    return self.convert_bandwidth_unit(value=value,
                                                       wavelength=param_1,
                                                       old_unit=old_unit,
                                                       new_unit=new_unit)
                elif conversion_type == self.UnitConversionEnumType.typeTime:
                    return self.convert_time_unit(value, old_unit, new_unit)
                elif conversion_type == self.UnitConversionEnumType.typeBitRate:
                    return self.convert_bitrate_unit(value, old_unit, new_unit)
                elif conversion_type == self.UnitConversionEnumType.typeAngle:
                    return self.convert_angle_unit(value, old_unit, new_unit)
                elif conversion_type == self.UnitConversionEnumType.typeDistance:
                    return self.convert_distance_unit(value, old_unit, new_unit)
                elif conversion_type == self.UnitConversionEnumType.typeTemperature:
                    return self.convert_temperature_unit(value, old_unit, new_unit)
                elif conversion_type == self.UnitConversionEnumType.typeTemperatureRate:
                    return self.convert_temperature_rate_unit(value, old_unit, new_unit)
                else:
                    raise ConversionError("{} do not include in convertible unit types,"
                                          "please look for the guide book".format(conversion_type))

            else:
                raise ConversionError("{} is a {} type,is not a float or int number".format(value, type(value)))

    def __find_unit_type(self, unit_str):
        """
            根据单位字符串寻找所属单位类别
        :param unit_str:
        :return:
        """
        if unit_str in self.POWER_UNIT:
            return self.UnitConversionEnumType.typePower
        elif unit_str in self.DISTANCE_UNIT:
            return self.UnitConversionEnumType.typeDistance
        elif unit_str in self.BANDWIDTH_UNIT:
            return self.UnitConversionEnumType.typeBandwidth
        elif unit_str in self.FREQUENCY_UNIT:
            return self.UnitConversionEnumType.typeFrequency
        elif unit_str in self.TIME_TYPE:
            return self.UnitConversionEnumType.typeTime
        elif unit_str in self.ANGELE_TYPE:
            return self.UnitConversionEnumType.typeAngle

    def evaluate_unit_type(self, old_unit_str, new_unit_str):
        """
            根据两个单位评估出它们共同所属的单位类别
        :param old_unit_str:
        :param new_unit_str:
        :return:
        """

        if self.__find_unit_type(old_unit_str) == self.__find_unit_type(new_unit_str):
            return self.__find_unit_type(old_unit_str)

    def watt_to_dBm(self, power) -> float:
        """
        将瓦特转为分贝毫瓦
        Convert watts to decibel milli watts
        formula: x dmb = 10log_{10}(power/(1 mW))
        :param power: unit [w]
        :return:
        """
        if power < MIN_POWER_VALUE:
            power = MIN_POWER_VALUE
            raise ConversionError("power:{} should be greater than {}".format(power, MIN_POWER_VALUE))
        else:
            return 10 * math.log10(power / 1.0e-3)

    def dBm_to_watt(self, dBm_value) -> float:
        """
        将分贝毫瓦转换成瓦特
        Convert decibel milli watts to watts
        :param dBm_value:
        :return:
        """
        return 1e-3 * math.pow(10, dBm_value / 10.0)

    def convert_to_watt(self, value, unit) -> float:
        """
        统一将功率转换成瓦特
        Convert power to watts in unity
        :param value: input value
        :param unit: input unit (string type)
        :return:
        """
        if unit == "nW":
            return value * 1e-9
        elif unit == "uW":
            return value * 1e-6
        elif unit == "mW":
            return value * 1e-3
        elif unit == "dBm":
            return self.dBm_to_watt(value)
        return value

    def convert_from_watt(self, value, unit) -> float:
        """
        从瓦特转换成其它功率单位
        Converting from Watts to other Power units
        :param value:
        :param unit:
        :return:
        """
        if unit == "nW":
            return value * 1e9
        elif unit == "uW":
            return value * 1e6
        elif unit == "mW":
            return value * 1e3
        elif unit == "dBm":
            return self.watt_to_dBm(value)
        return value

    def convert_power_unit(self, value, old_unit, new_unit) -> float:
        return self.convert_from_watt(self.convert_to_watt(value, old_unit), new_unit)

    def frequency_to_wavelength(self, wave_length_m) -> float:
        """
        频率转换为波长,单位:[Hz->m]
        Convert frequency to wavelength, unit:[Hz->m]
        :param wave_length_m: wavelength
        :return:
        """
        return constants.LIGHT_SPEED_MS / wave_length_m

    def wave_length_to_frequency(self, frequency_Hz) -> float:
        """
        将波长转换成频率,单位[m->Hz]
        Convert wavelength to frequency, unit:[m->Hz]
        :param frequency_Hz: frequency
        :return:
        """
        return constants.LIGHT_SPEED_MS / frequency_Hz

    def bandwidth_freq_to_wave(self, band_Hz, wavelength_m):
        """
        带宽频率与波长换算。
        频率：v
        光速：c
        波长：λ
        相干长度：△x
        （1）c=v*λ
        （2）△v=c/(λ*λ)*△λ
        （3）△x=c/△v
        bandwidth Frequency to Wavelength Conversion
        :param band_Hz :
        :param wavelength_m :
        :return:
        """
        return band_Hz / constants.LIGHT_SPEED_MS * math.pow(wavelength_m, 2)

    def bandwidth_wave_to_freq(self, band_m, wavelength_m):
        return constants.LIGHT_SPEED_MS / (math.pow(wavelength_m, 2) * band_m)

    def convert_to_Hz(self, value, wavelength, unit):
        if unit == "kHz":
            return value * 1e3
        elif unit == "MHz":
            return value * 1e6
        elif unit == "GHz":
            return value * 1e9
        elif unit == "THz":
            return value * 1e12
        elif unit == "m":
            return self.bandwidth_wave_to_freq(value, wavelength)
        elif unit == "mm":
            return self.bandwidth_wave_to_freq(value * 1e-3, wavelength)
        elif unit == "um":
            return self.bandwidth_wave_to_freq(value * 1e-6, wavelength)
        elif unit == "nm":
            return self.bandwidth_wave_to_freq(value * 1e-9, wavelength)
        elif unit == "a":
            return self.bandwidth_wave_to_freq(value * 1e-10, wavelength)

        return value

    def convert_from_Hz(self, value, wavelength, unit):
        if unit == "kHz":
            return value / 1e3
        elif unit == "MHz":
            return value / 1e6
        elif unit == "GHz":
            return value / 1e9
        elif unit == "THz":
            return value / 1e12
        elif unit == "m":
            return self.bandwidth_freq_to_wave(value, wavelength)
        elif unit == "mm":
            return self.bandwidth_freq_to_wave(value, wavelength) * 1e3
        elif unit == "um":
            return self.bandwidth_freq_to_wave(value, wavelength) * 1e6
        elif unit == "nm":
            return self.bandwidth_freq_to_wave(value, wavelength) * 1e9
        elif unit == "a":
            return self.bandwidth_freq_to_wave(value, wavelength) * 1e10
        return value

    def convert_frequency_unit(self, value, old_unit, new_unit):
        """
        频率单位换算入口,分为两种情况,一种是单纯的频率单位转换,第二种是带宽
        :param value:
        :param old_unit:
        :param new_unit:
        :param wavelength:
        :return:
        """
        return self.convert_from_Hz(self.convert_to_Hz(value, None, old_unit), None, new_unit)

    def convert_bandwidth_unit(self, value, wavelength, old_unit, new_unit):
        return self.convert_from_Hz(
            value=(self.convert_to_Hz(value=value, wavelength=wavelength, unit=old_unit)),
            wavelength=wavelength,
            unit=new_unit)

    def convert_time_unit(self, value, old_unit, new_unit):
        """
        用于转换时间单位
        This function is used to convert time units.
        :param value:
        :param old_unit:
        :param new_unit:
        :return:
        """

        if old_unit == "s":
            if new_unit == "min":
                return value / constants.CONST_MINUTE
            elif new_unit == "h":
                return value / constants.CONST_HOUR
            elif new_unit == "ms":
                return value * 1e3
            elif new_unit == "us":
                return value * 1e6
            elif new_unit == "ns":
                return value * 1e9
            elif new_unit == "ps":
                return value * 1e12
            elif new_unit == "fs":
                return value * 1e15

        elif old_unit == "ms":
            if new_unit == "s":
                return value / 1e3
            elif new_unit == "us":
                return value * 1e3
            elif new_unit == "ns":
                return value * 1e6
            elif new_unit == "ps":
                return value * 1e9
            elif new_unit == "fs":
                return value * 1e12
            elif new_unit == "min":
                return (value / 1e3) / constants.CONST_MINUTE
            elif new_unit == "h":
                return (value / 1e3) / constants.CONST_HOUR

        elif old_unit == "us":
            if new_unit == "s":
                return value / 1e6
            elif new_unit == "ms":
                return value / 1e3
            elif new_unit == "ns":
                return value * 1e3
            elif new_unit == "ps":
                return value * 1e6
            elif new_unit == "fs":
                return value * 1e9
            elif new_unit == "min":
                return (value / 1e6) / constants.CONST_MINUTE
            elif new_unit == "h":
                return (value / 1e6) / constants.CONST_HOUR

        elif old_unit == "ns":
            if new_unit == "s":
                return value / 1e9
            elif new_unit == "ms":
                return value / 1e6
            elif new_unit == "us":
                return value / 1e3
            elif new_unit == "ps":
                return value * 1e3
            elif new_unit == "fs":
                return value * 1e6
            elif new_unit == "min":
                return (value / 1e9) / constants.CONST_MINUTE
            elif new_unit == "h":
                return (value / 1e9) / constants.CONST_HOUR

        elif old_unit == "ps":
            if new_unit == "s":
                return value / 1e12
            elif new_unit == "ms":
                return value / 1e9
            elif new_unit == "us":
                return value / 1e6
            elif new_unit == "ns":
                return value / 1e3
            elif new_unit == "fs":
                return value * 1e3
            elif new_unit == "min":
                return (value / 1e12) / constants.CONST_MINUTE
            elif new_unit == "h":
                return (value / 1e12) / constants.CONST_HOUR

        elif old_unit == "fs":
            if new_unit == "s":
                return value / 1e15
            elif new_unit == "ms":
                return value / 1e2
            elif new_unit == "us":
                return value / 1e9
            elif new_unit == "ns":
                return value / 1e6
            elif new_unit == "ps":
                return value / 1e3
            elif new_unit == "min":
                return (value / 1e15) / constants.CONST_MINUTE
            elif new_unit == "h":
                return (value / 1e15) / constants.CONST_HOUR

        elif old_unit == "min":
            if new_unit == "s":
                return value * constants.CONST_MINUTE
            elif new_unit == "ms":
                return value * constants.CONST_MINUTE * 1e3
            elif new_unit == "us":
                return value * constants.CONST_MINUTE * 1e6
            elif new_unit == "ns":
                return value * constants.CONST_MINUTE * 1e9
            elif new_unit == "ps":
                return value * constants.CONST_MINUTE * 1e12
            elif new_unit == "fs":
                return value * constants.CONST_MINUTE * 1e15

        elif old_unit == "h":
            if new_unit == "s":
                return value * constants.CONST_HOUR
            elif new_unit == "min":
                return value * constants.CONST_MINUTE
            elif new_unit == "ms":
                return value * constants.CONST_HOUR * 1e3
            elif new_unit == "us":
                return value * constants.CONST_HOUR * 1e6
            elif new_unit == "ns":
                return value * constants.CONST_HOUR * 1e9
            elif new_unit == "ps":
                return value * constants.CONST_HOUR * 1e12
            elif new_unit == "fs":
                return value * constants.CONST_HOUR * 1e15

        return value

    def convert_bitrate_unit(self, value, old_unit, new_unit):
        if old_unit == "MBits/s":
            old_unit = "Mbit/s"
        if old_unit == "Bits/s":
            old_unit = "bit/s"
        if old_unit == "GBits/s":
            old_unit = "Gbit/s"
        if old_unit == "KBits/s":
            old_unit = "Kbit/s"
        if new_unit == "MBits/s":
            new_unit = "Mbit/s"
        if new_unit == "Bits/s":
            new_unit = "bit/s"
        if new_unit == "GBits/s":
            new_unit = "Gbit/s"
        if new_unit == "KBits/s":
            new_unit = "Kbit/s"

        if old_unit == "bit/s":
            if new_unit == "Kbit/s":
                return value / 1e3
            elif new_unit == "Mbit/s":
                return value / 1e6
            elif new_unit == "Gbit/s":
                return value / 1e9
        elif old_unit == "Mbit/s":
            if new_unit == "bit/s":
                return value * 1e6
            elif new_unit == "Kbit/s":
                return value * 1e6 / 1e3
            elif new_unit == "Gbit/s":
                return value * 1e6 / 1e9
        elif old_unit == "Gbit/s":
            if new_unit == "bit/s":
                return value * 1e9
            elif new_unit == "Kbit/s":
                return value * 1e9 / 1e3
            elif new_unit == "Mbit/s":
                return value * 1e9 / 1e6
        return value

    def radians_to_degrees(self, value):
        """
            弧度转换成角度
        :param value:
        :return:
        """
        return value * 180.0 / constants.M_PI

    def degrees_to_radians(self, value):
        """
            角度转换成弧度
        :param value:
        :return:
        """
        return value * constants.M_PI / 180.0

    def convert_angle_unit(self, value, old_unit, new_unit):
        if old_unit == "rad":
            if new_unit == "deg":
                return self.radians_to_degrees(value)
            elif new_unit == "mrad":
                return value * 1.0e3
            elif new_unit == "urad":
                return value * 1.0e6
        elif old_unit == "deg":
            if new_unit == "rad":
                return self.degrees_to_radians(value)
            elif new_unit == "mrad":
                return self.degrees_to_radians(value) * 1.0e3
            elif new_unit == "urad":
                return self.degrees_to_radians(value) * 1.0e6
        elif old_unit == "mrad":
            if new_unit == "deg":
                return self.radians_to_degrees(value * 1.0e-3)
            elif new_unit == "rad":
                return value * 1.0e-3
            elif new_unit == "urad":
                return value * 1.0e3
        elif old_unit == "urad":
            if new_unit == "deg":
                return self.radians_to_degrees(value * 1.0e-6)
            elif new_unit == "rad":
                return value * 1.0e-6
            elif new_unit == "mrad":
                return value * 1.0e-3
        return value

    def convert_distance_unit(self, value, old_unit, new_unit):
        """
            距离单位转换函数
        :param value:
        :param old_unit:
        :param new_unit:
        :return:
        """
        if old_unit == "um":
            if new_unit == "cm":
                return value / 1e4
            elif new_unit == "mm":
                return value / 1e3
            elif new_unit == "m":
                return value / 1e6
            elif new_unit == "km":
                return value / 1e9
            elif new_unit == "nm":
                return value * 1e3
        elif old_unit == "cm":
            if new_unit == "nm":
                return value * 1e7
            elif new_unit == "um":
                return value * 1e4
            elif new_unit == "mm":
                return value * 10
            elif new_unit == "m":
                return value / 1e2
            elif new_unit == "km":
                return value / 1e5
        elif old_unit == "m":
            if new_unit == "nm":
                return value * 1e9
            elif new_unit == "um":
                return value * 1e6
            elif new_unit == "mm":
                return value * 1e3
            elif new_unit == "cm":
                return value * 1e2
            elif new_unit == "km":
                return value / 1e3
        elif old_unit == "km":
            if new_unit == "nm":
                return value * 1e12
            elif new_unit == "um":
                return value * 1e9
            elif new_unit == "mm":
                return value * 1e6
            elif new_unit == "cm":
                return value * 1e5
            elif new_unit == "m":
                return value * 1e3
        elif old_unit == "mm":
            if new_unit == "nm":
                return value * 1e6
            elif new_unit == "um":
                return value * 1e3
            elif new_unit == "cm":
                return value / 10
            elif new_unit == "m":
                return value / 1e3
            elif new_unit == "km":
                return value / 1e6
        elif old_unit == "nm":
            if new_unit == "um":
                return value / 1e3
            elif new_unit == "mm":
                return value / 1e6
            elif new_unit == "cm":
                return value / 1e7
            elif new_unit == "m":
                return value / 1e9
            elif new_unit == "km":
                return value / 1e12
        return value

    def convert_temperature_unit(self, value, old_unit, new_unit):
        """
            温度单位转换函数
        :param value:
        :param old_unit:
        :param new_unit:
        :return:
        """
        # first - convert to Centigrade
        if old_unit.find("K") >= 0:
            centigrade = value - 273.15
            if new_unit.find("C") >= 0:
                return centigrade
            elif new_unit.find("F") >= 0:
                return (9.0 / 5.0) * centigrade + 32
        elif old_unit.find("C") >= 0:
            if new_unit.find("K") >= 0:
                return value + 273.15
            elif new_unit.find("F") >= 0:
                return (9.0 / 5.0) * value + 32
        elif old_unit.find("F") >= 0:
            centigrade = (5.0 / 9.0) * (value - 32)
            if new_unit.find("C") >= 0:
                return centigrade
            elif new_unit.find("K") >= 0:
                return centigrade + 273.15
        return value

    def convert_temperature_rate_unit(self, value, old_unit, new_unit):
        """
            针对 /℃ /℉ /K 进行转换
        :param value:
        :param old_unit:
        :param new_unit:
        :return:
        """
        # Temperature unit conversion
        if abs(value - 0.0) <= 1e-15:
            return 0
        else:
            old_temperature_unit = ''
            new_temperature_unit = ''

            if old_unit.find("/C") >= 0:
                old_temperature_unit = "C"
            elif old_unit.find("/K") >= 0:
                old_temperature_unit = "K"
            elif old_unit.find("/F") >= 0:
                old_temperature_unit = "F"

            if new_unit.find("/C") >= 0:
                new_temperature_unit = "C"
            elif new_unit.find("/K") >= 0:
                new_temperature_unit = "K"
            elif new_unit.find("/F") >= 0:
                new_temperature_unit = "F"

            return 1.0 / self.convert_temperature_unit(1.0 / value, old_temperature_unit, new_temperature_unit)


if __name__ == '__main__':
    def power_unit_conversion_test(power_value=1, old_unit="mW", new_unit="dBm"):
        uc = UnitConversion()
        print("Power Conversion Test:")
        print("{} {} = {} {}".format(power_value,
                                     old_unit,
                                     uc.convert(uc.UnitConversionEnumType.typePower, power_value, old_unit, new_unit),
                                     new_unit))


    def frequency_unit_conversion_test(value, old_unit, new_unit, ):
        uc = UnitConversion()
        print("Frequency Conversion Test:")
        print("{} {} = {} {}".format(value,
                                     old_unit,
                                     uc.convert(uc.UnitConversionEnumType.typeFrequency,
                                                value,
                                                old_unit,
                                                new_unit),
                                     new_unit))


    def bandwidth_unit_conversion_test(value, old_unit, new_unit, wavelength):
        uc = UnitConversion()
        print("Bandwidth Conversion Test:")
        print("{} {} = {} {}".format(value,
                                     old_unit,
                                     uc.convert(uc.UnitConversionEnumType.typeBandwidth,
                                                value,
                                                old_unit,
                                                new_unit,
                                                wavelength),
                                     new_unit))


    def time_unit_conversion_test(value, old_unit, new_unit):
        uc = UnitConversion()
        print("Time Conversion Test:")
        print("{} {} = {} {}".format(value,
                                     old_unit,
                                     uc.convert(uc.UnitConversionEnumType.typeTime,
                                                value,
                                                old_unit,
                                                new_unit, ),
                                     new_unit))


    def bit_rate_unit_conversion_test(value, old_unit, new_unit):
        uc = UnitConversion()
        print("BiteRate Conversion Test:")
        print("{} {} = {} {}".format(value,
                                     old_unit,
                                     uc.convert(uc.UnitConversionEnumType.typeBitRate,
                                                value,
                                                old_unit,
                                                new_unit, ),
                                     new_unit))


    def radians_conversion_test(value, old_unit, new_unit):
        uc = UnitConversion()
        print("Radians Conversion Test:")
        print("{} {} = {} {}".format(value,
                                     old_unit,
                                     uc.convert(uc.UnitConversionEnumType.typeAngle,
                                                value,
                                                old_unit,
                                                new_unit, ),
                                     new_unit))


    def distance_conversion_test(value, old_unit, new_unit):
        uc = UnitConversion()
        print("Distance Conversion Test:")
        print("{} {} = {} {}".format(value,
                                     old_unit,
                                     uc.convert(uc.UnitConversionEnumType.typeDistance,
                                                value,
                                                old_unit,
                                                new_unit, ),
                                     new_unit))


    def temperature_conversion_test(value, old_unit, new_unit):
        uc = UnitConversion()
        print("Temperature Conversion Test:")
        print("{} {} = {} {}".format(value,
                                     old_unit,
                                     uc.convert(uc.UnitConversionEnumType.typeTemperature,
                                                value,
                                                old_unit,
                                                new_unit, ),
                                     new_unit))


    def temperature_rate_conversion_test(value, old_unit, new_unit):
        uc = UnitConversion()
        print("Temperature Rate Conversion Test:")
        print("{} {} = {} {}".format(value,
                                     old_unit,
                                     uc.convert(uc.UnitConversionEnumType.typeTemperatureRate,
                                                value,
                                                old_unit,
                                                new_unit, ),
                                     new_unit))


    power_unit_conversion_test(power_value=1, old_unit="mW", new_unit="dBm")
    frequency_unit_conversion_test(value=1, old_unit="kHz", new_unit="Hz")
    bandwidth_unit_conversion_test(value=1553.0, old_unit="nm", new_unit="kHz", wavelength=1)
    time_unit_conversion_test(value=1, old_unit="h", new_unit="ms")
    bit_rate_unit_conversion_test(1, "Mbit/s", "Kbit/s")
    radians_conversion_test(180, "deg", "rad")
    distance_conversion_test(1, "km", "m")
    temperature_conversion_test(1, "°C", "K")
    # 0.0036476381542950944 = 1/274.15
    temperature_rate_conversion_test(1, "/C", "/K")
